package cs180battleships;

import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.SwingUtilities;

public class GameClient implements Runnable, GameStateChangedListener, GameBoardListener{

	private String idText;
	private String displayMessage;
	private Socket connection; // connection to the server
	private Scanner input; // input from server
	private Formatter output; // output to server
	private String BattleShipsHost; // host name for server
	private String myMark; // this client's mark
	private boolean myTurn; // determines which client's turn it is
	private final String X_MARK = "X"; // mark for first client
	private final String O_MARK = "O"; // mark for second client
	private ArrayList clientChangedListers = new ArrayList();
	GameBoard battleshipBoard;


	// set up user-interface and board
	public GameClient(String host) {
		BattleShipsHost = host; // set name of server

		battleshipBoard= new GameBoard();
		battleshipBoard.addGameBoardListener(this);
		
		startClient();
	} // end BattleShipsClient constructor


	// start the client thread
	public void startClient() {
		try {
			// make connection to server
			connection = new Socket(BattleShipsHost, 12345);
			// get streams for input and output
			input = new Scanner(connection.getInputStream());
			output = new Formatter(connection.getOutputStream());
		} // end try
		catch (IOException ioException) {
			ioException.printStackTrace();
		} // end catch

		// create and start worker thread for this client
		ExecutorService worker = Executors.newFixedThreadPool(1);
		worker.execute(this); // execute client
	} // end method startClient


	// control thread that allows continous update of displayArea
	public void run() {
		myMark = input.nextLine(); // get player's mark (X or O)
		// "O hi Mark!"
		final String playerNumber;
		if(myMark.equals("X")){
			playerNumber="1";
		}else{
			playerNumber="2";	
		}
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {
				// display player's mark
				battleshipBoard.setIdText("You are Player\"" + playerNumber + "\"");
				//setIdText("You are Player\"" + playerNumber + "\"");
				////idField.setText("You are Player\"" + playerNumber + "\"");
			} // end method run
		} // end anonymous inner class
				); // end call to SwingUtilities.InvokeLater

		myTurn = (myMark.equals(X_MARK)); // determine if client's turn
		battleshipBoard.myTurn=myTurn;
		// receive messages sent to client and output them
		while (true) {
			if (input.hasNextLine())
				battleshipBoard.processMessage(input.nextLine());
		} // end while
	} // end method run

	public void sendMove(int location) {
		// if it is my turn
		//if (myTurn) {
			// playAudio(shotFired);
			output.format("%d\n", location); // send location to server
			output.flush();
		//	myTurn = false; // not my turn any more
		//} // end if
	} // end method sendClickedSquare

	public void skipInputLine(){
		input.nextLine(); // skip newline
	}
	public int getIntInput(){
		int i=input.nextInt(); // get move location
		return i;
	}

	@SuppressWarnings("unchecked")
	public void addClientChangedListener(ClientChangedListener listener) {
		clientChangedListers.add(listener);
	}


	/**
	 * Allows an observer to unregister for BalanceChanged events.
	 */
	public void removeClientChangedListener(ClientChangedListener listener) {
		clientChangedListers.remove(listener);
	}


	/**
	 * Iterates through all listeners, informing them that a BalanceChanged event has occurred.
	 */
	private void fireClientChanged() {
		for (int i = 0; i < clientChangedListers.size(); i++) {
			ClientChangedListener listener = (ClientChangedListener) clientChangedListers.get(i);
			listener.clientChanged(this);
		}
	}


	public void setDisplayMessage(String displayMessage) {
		this.displayMessage = displayMessage;
		fireClientChanged();
	}


	public String getDisplayMessage() {
		return displayMessage;
	}


	public void setIdText(String idText) {
		this.idText = idText;
	}


	public String getIdText() {
		return idText;
	}


	@Override
	public void gameStateChanged(GameState gameState) {
		// TODO Auto-generated method stub
		//playAudio(gameState.getAudioFileName());
	}
	public void updateGameBoard(GameBoard gameBoard){
		gameBoard.setInput(getIntInput());
		skipInputLine();
		
	}
	public void gameBoardChanged(GameBoard gameBoard){
		sendMove(gameBoard.clickedSquare);
		
	}
}
